Current File : /home/jeconsul/public_html/wp-content/plugins/suremails/src/screens/settings/settings.js |
// File: src/components/Settings.js
import { useLayoutEffect, useState } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import {
Button,
Switch,
Select,
Label,
Skeleton,
toast,
Tooltip,
} from '@bsf/force-ui';
import { fetchSettings, saveSettings } from '@api/settings';
import SettingsSkeleton from './settings-skeleton';
import Title from '@components/title/title';
import { Info, LoaderCircle as LoaderIcon } from 'lucide-react'; // Added LoaderIcon and ChevronLeftIcon
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import SafeGuardSection from './safe-guard-section';
const Settings = () => {
const { data: settingsData, isLoading: isSettingsLoading } = useQuery( {
queryKey: [ 'settings' ],
queryFn: fetchSettings,
select: ( response ) => response.data,
refetchInterval: 100000, // Refetch every 10 minutes
refetchOnMount: false,
refetchOnWindowFocus: false,
refetchOnReconnect: true,
} );
const queryClient = useQueryClient();
const { mutate: saveSettingsMutation, isPending: isSaving } = useMutation( {
mutationFn: saveSettings,
onSuccess: ( data ) => {
queryClient.setQueryData( [ 'settings' ], data );
toast.success( __( 'Settings saved successfully', 'suremails' ), {
description: __( 'Your changes have been saved.', 'suremails' ),
} );
},
onError: ( error ) => {
toast.error( __( 'Error saving settings', 'suremails' ), {
description:
error.message ||
__(
'There was an issue saving the settings.',
'suremails'
),
} );
},
} );
const [ formState, setFormState ] = useState( {
logEmails: false,
deleteEmailLogsAfter: '30_days',
defaultConnection: {
type: '',
email: '',
id: '',
connection_title: '',
},
emailSimulation: false,
} );
useLayoutEffect( () => {
if ( settingsData ) {
// Update form state with fetched data
setFormState( {
logEmails: settingsData.log_emails === 'yes',
deleteEmailLogsAfter:
settingsData.log_emails === 'yes'
? settingsData.delete_email_logs_after || '30_days'
: 'none',
defaultConnection: {
type: settingsData?.default_connection?.type || '',
email: settingsData?.default_connection?.email || '',
id: settingsData?.default_connection?.id || '',
connection_title:
settingsData?.default_connection?.connection_title ||
'',
},
emailSimulation: settingsData.email_simulation === 'yes',
} );
}
}, [ settingsData ] );
// Define Delete Logs Options Array
const deleteLogsOptions = [
{ label: __( 'Delete after 1 day', 'suremails' ), value: '1_day' },
{ label: __( 'Delete after 7 days', 'suremails' ), value: '7_days' },
{ label: __( 'Delete after 30 days', 'suremails' ), value: '30_days' },
{ label: __( 'Delete after 60 days', 'suremails' ), value: '60_days' },
{ label: __( 'Delete after 90 days', 'suremails' ), value: '90_days' },
{ label: __( 'Never', 'suremails' ), value: 'none' },
];
const handleChange = ( field, value ) => {
setFormState( ( prevState ) => ( {
...prevState,
[ field ]: value,
} ) );
};
const hasChanges = () => {
return (
formState.logEmails !== ( settingsData?.log_emails === 'yes' ) ||
formState.deleteEmailLogsAfter !==
settingsData?.delete_email_logs_after ||
formState.defaultConnection.id !==
settingsData?.default_connection?.id ||
formState.emailSimulation !==
( settingsData?.email_simulation === 'yes' )
);
};
const handleSave = async () => {
if ( ! hasChanges() ) {
toast.info( __( 'No changes to save.', 'suremails' ) );
return;
}
const updatedSettings = {
settings: {
delete_email_logs_after: formState.deleteEmailLogsAfter,
email_simulation: formState.emailSimulation ? 'yes' : 'no',
log_emails: formState.logEmails ? 'yes' : 'no',
default_connection: formState.defaultConnection.email
? formState.defaultConnection
: {
type: '',
email: '',
id: '',
connection_title: '',
},
},
};
saveSettingsMutation( updatedSettings );
};
// Prepare connection options formatted as Email (Provider) for the default connection
const defaultConnectionOptions = Object.entries(
settingsData?.connections || {}
).map( ( [ key, connection ] ) => ( {
label: `${ connection.connection_title } - ${ connection.type } : ${ connection.from_email }`,
value: {
id: key,
email: connection.from_email,
type: connection.type,
connection_title: connection.connection_title,
},
} ) );
// Find the label for the selected connection value
const getConnectionLabel = ( connection ) => {
return connection?.email
? `${ connection.connection_title } - ${ connection.type } : ${ connection.email }`
: __( 'None', 'suremails' );
};
const getDeleteLogsLabel = ( value ) => {
const label = deleteLogsOptions.find(
( option ) => option.value === value
);
return label ? label.label : '';
};
// Handle loading state
if ( isSettingsLoading ) {
return <SettingsSkeleton />;
}
// Determine if there are connections available
const hasConnections = defaultConnectionOptions.length > 0;
return (
<>
<div className="flex flex-col gap-6 p-8 overflow-hidden overflow-x-hidden overflow-y-hidden">
<div className="flex items-center justify-between max-w-settings-container w-full h-auto gap-2 mx-auto">
<Title
size="md"
title={ __( 'General Settings', 'suremails' ) }
tag="h1"
/>
<Button
onClick={ handleSave }
variant="primary"
size="md"
className="font-medium"
loading={ isSaving }
icon={
isSaving ? (
<LoaderIcon className="mr-2 animate-spin" />
) : null
}
>
{ isSaving
? __( 'Saving…', 'suremails' )
: __( 'Save', 'suremails' ) }
</Button>
</div>
<div className="px-6 py-6 bg-background-primary rounded-xl shadow-sm max-w-settings-container w-full h-auto gap-4 opacity-100 mx-auto mt-2 flex flex-col">
{ /* Log Emails */ }
<div className="flex w-[648px] gap-3">
<Switch
checked={ formState.logEmails }
onChange={ ( value ) => {
handleChange( 'logEmails', value );
if ( ! value ) {
handleChange(
'deleteEmailLogsAfter',
'none'
);
}
} }
size="sm"
label={ {
heading: __( 'Log Emails', 'suremails' ),
description: __(
'Enable to log all outgoing emails for reference.',
'suremails'
),
} }
/>
</div>
{ /* Log Emails and Delete Logs */ }
{ formState.logEmails && (
<div className="flex flex-col w-full h-auto gap-1.5">
<Select
value={ formState.deleteEmailLogsAfter }
onChange={ ( value ) =>
handleChange(
'deleteEmailLogsAfter',
value
)
}
className="w-full h-auto"
>
<Select.Button
label={
<div className="flex items-center">
<Label tag="span" size="sm">
{ __(
'Delete Logs',
'suremails'
) }
</Label>
<Tooltip
arrow
content={
<span>
{ __(
'Email logs stored in the database will be deleted after the selected duration automatically.',
'suremails'
) }
</span>
}
placement="bottom"
title={ __(
'Delete Logs',
'suremails'
) }
triggers={ [ 'hover' ] }
variant="dark"
tooltipPortalRoot="suremails-root-app"
tooltipPortalId="suremails-root-app"
>
<Info className="w-4 h-4 ml-1 cursor-pointer text-icon-secondary" />
</Tooltip>
</div>
}
>
{ getDeleteLogsLabel(
formState.deleteEmailLogsAfter
) }
</Select.Button>
<Select.Options className="z-999999">
{ deleteLogsOptions.map( ( option ) => (
<Select.Option
key={ option.value }
value={ option.value }
>
{ option.label }
</Select.Option>
) ) }
</Select.Options>
</Select>
<Label tag="p" size="sm" variant="help">
{ __(
'Logs will be automatically deleted after the chosen duration.',
'suremails'
) }
</Label>
</div>
) }
<LineSkeleton />
{ /* Default Connection */ }
<div className="flex flex-col w-full h-auto gap-1.5">
<Select
by="id"
value={ formState.defaultConnection }
onChange={ ( value ) =>
handleChange( 'defaultConnection', value )
}
className="w-full h-auto"
disabled={ ! hasConnections }
>
<Select.Button
label={ __(
'Default Connection',
'suremails'
) }
>
{ getConnectionLabel(
formState.defaultConnection
) }
</Select.Button>
<Select.Options className="z-999999">
{ defaultConnectionOptions.map( ( option ) => (
<Select.Option
key={ option.value.id }
value={ option.value }
>
{ option.label }
</Select.Option>
) ) }
</Select.Options>
</Select>
<Label tag="p" size="sm" variant="help">
{ __(
'This connection will be used by default unless a specific "from email" address is provided in the email headers.',
'suremails'
) }
</Label>
</div>
<LineSkeleton />
{ /* Email Simulation */ }
<div className="flex w-[648px] gap-3">
<Switch
checked={ formState.emailSimulation }
onChange={ ( value ) => {
handleChange( 'emailSimulation', value );
} }
size="sm"
label={ {
heading: __( 'Email Simulation', 'suremails' ),
description: __(
'Disable sending all emails. If you enable this, no email will be sent but the email logs will be recorded here.',
'suremails'
),
} }
/>
</div>
</div>
{ /* Safe Guard Settings */ }
<SafeGuardSection />
</div>
</>
);
};
/*
* Line Skeleton Component
* Used to show a divider line between settings sections
*/
const LineSkeleton = () => {
return (
<Skeleton
className="w-full h-px mt-2 mb-2 border opacity-100 border-border-subtle"
variant="rectangular"
/>
);
};
export default Settings;